#include <stdio.h>

/*
 * 1.字符指针
 * 2.数组指针
 * 3.指针数组
 * 4.数组传参和指针传参
 * 5.函数指针
 * 6.函数指针数组
 * 7.指向函数指针数组的指针
 * 8.回调函数
 */

// 练习，解释下列代码
// int *p_arr1[5];
// int (*p_arr2)[5];
// int *p_arr3[10][5];
// int (*p_arr4[10])[5];
//
// p_arr1 是指针数组，有 5 个元素，每个元素是 int* 类型
// p_arr2 是数组指针，指向 int 数组，该数组有 5 个元素
// p_arr3 是二维数组，每个元素是 int* 类型
// p_arr4 是数组，有 10 个元素，每个元素是数组指针，该指针指向 int 数组，该数组有 5 个元素

// 数组传参和指针传参
//
// 数组作实参时，形参可以是对应的数组或指针，
// 因为数组传参会发生类型退化。
//
// 一级指针作形参，实参可以是一级指针，变量地址，一维数组
// 二级指针作形参，实参可以是二级指针，一级指针地址，一维指针数组

// 数组指针，指向数组的指针

// 一些数组及其相应的指针
// int main()
// {
//     int arr1[5][10];
//     int(*p1)[10] = arr1;
//
//     int(*arr2[5][10])[10];
//     int(*(*p2)[10])[10] = arr2;
//
//     int *arr3[5][10];
//     int *(*p3)[10] = arr3;
//
//     int *(*arr4[5][10])[10];
//     int *(*(*p4)[10])[10] = arr4;
//     return 0;
// }
// 提醒：
// 在声明中去掉变量名即为变量的类型，
// （数组除外）
// 在声明中去掉数组名和 [] 即为数组元素的类型

// 用数组指针作形参，接收二维数组传参

// 指针数组，存放指针的数组

// 用指针数组管理多个数组
// int main()
// {
//     int arr1[] = {1, 2, 3};
//     int arr2[] = {4, 5, 6};
//     int arr3[] = {7, 8, 9};
//     int *parr[] = {arr1, arr2, arr3};
//     return 0;
// }

// 字符指针

// 字符串两种表示方法
// int main()
// {
//     // 方法一：字符数组
//     char arr[] = "abcdef";
//     char *str = arr;
//     printf("%s\n", arr);
//     printf("%s\n", str);
//
//     // 方法二：字符串常量（不能改变）
//     // char *p = "abcdef";
//     const char *p = "abcdef"; // 准确写法
//     printf("%s\n", p);
//     printf("%c\n", *p);
//     // *p = 'A';
//     // printf("%c\n", *p);
//     // 报错。字符串常量不能改变
//     return 0;
// }
// 字符指针能够指向常量字符串，说明常量字符串一定存在于内存某处。
// （注：C/C++ 用一个单独的内存区域来存放常量字符串）
// 同时，常量字符串，本质上是该字符串首字符的地址常量
// （类似于数组名）
// （这个写法是允许的："0123456789"[i]）
// （注意：字符数组初始化用的 "" 不是常量字符串）

// 探究字符串常量的存储
// int main()
// {
//     printf("%p\n", "abcdef");
//
//     const char *p = "abcdef";
//     const char *p2 = "abcde";
//     const char *p3 = "abcd";
//     printf("%p\n", p);
//     printf("%p\n", "abcdef");
//     printf("%p\n", p2);
//     printf("%p\n", "abcde");
//     printf("%p\n", p3);
//     printf("%p\n", "abcd");
//     return 0;
// }
